/*
 * Copyright (C) 2019-2020 Alibaba Group Holding Limited
 */

#include <aos/aos.h>
#include "gif_lib.h"
#include "gif_decoder.h"
#include "lscreen_stream/stream.h"

#define TAG "gif"

#define MIN(x, y) ((x) > (y) ? (y) : (x))

struct _gif_decoder_handler_t {
    lstream_cls_t *stream;
    GifFileType *gif_file;
    GifRowType *screen_buf;
    // int         file_terminated;
};

static int stream_read(GifFileType *file, GifByteType *buf, int len)
{
    CHECK_PARAM(file && file->UserData && buf && len > 0, -1);

    gif_decoder_handler_t *hdl = file->UserData;

    return hdl->stream ? lstream_read(hdl->stream, buf, len) : -1;
}

static int read_image(gif_decoder_handler_t *hdl, uint8_t *image_r, uint8_t *image_g, uint8_t *image_b)
{
    CHECK_PARAM(hdl && hdl->gif_file, -1);
    
    int i, j;
    GifFileType *gif_file = hdl->gif_file;
    GifRowType *screen_buf = hdl->screen_buf;
    int Row, Col, Width, Height;
    int InterlacedOffset[] = {0, 4, 2, 1}; /* The way Interlaced image should. */
    int InterlacedJumps[]  = {8, 8, 4, 2}; /* be read - offsets and jumps... */
    ColorMapObject *ColorMap;

    Row    = gif_file->Image.Top; /* Image Position relative to Screen. */
    Col    = gif_file->Image.Left;
    Width  = gif_file->Image.Width;
    Height = gif_file->Image.Height;

    if (gif_file->Image.Left + gif_file->Image.Width > gif_file->SWidth ||
        gif_file->Image.Top + gif_file->Image.Height > gif_file->SHeight) {
        LOGE(TAG, "Image %d is not confined to screen dimension, aborted.",
                gif_file->ImageCount);
        return -1;
    }

    if (gif_file->Image.Interlace) {
        /* Need to perform 4 passes on the images: */
        for (i = 0; i < 4; i++)
            for (j = Row + InterlacedOffset[i]; j < Row + Height; j += InterlacedJumps[i]) {
                if (DGifGetLine(gif_file, &screen_buf[j][Col], Width) == GIF_ERROR) {
                    PrintGifError(gif_file->Error);
                    return -1;
                }
            }
    } else {
        for (i = 0; i < Height; i++) {
            if (DGifGetLine(gif_file, &screen_buf[Row++][Col], Width) == GIF_ERROR) {
                PrintGifError(gif_file->Error);
                return -1;
            }
        }
    }

    /* Lets dump it - set the global variables required and do it: */
    ColorMap = (gif_file->Image.ColorMap ? gif_file->Image.ColorMap : gif_file->SColorMap);
    if (ColorMap == NULL) {
        LOGE(TAG, "Gif Image does not have a colormap");
        return -1;
    }

    /* check that the background color isn't garbage (SF bug #87) */
    if (gif_file->SBackGroundColor < 0 || gif_file->SBackGroundColor >= ColorMap->ColorCount) {
        LOGE(TAG, "Background color out of range for colormap");
        return -1;
    }

    for (i = 0; i < gif_file->SHeight; i++) {
        GifRowType GifRow = screen_buf[i];
        for (j = 0; j < gif_file->SWidth; j++) {
            GifColorType *ColorMapEntry = &ColorMap->Colors[GifRow[j]];

            if (image_r) {
                image_r[i * gif_file->SWidth + j] = ColorMapEntry->Red;
            }

            if (image_g) {
                image_g[i * gif_file->SWidth + j] = ColorMapEntry->Green;
            }

            if (image_b) {
                image_b[i * gif_file->SWidth + j] = ColorMapEntry->Blue;
            }
        }
    }

    return 0;
}

gif_decoder_handler_t *gif_new(const char *url)
{
    CHECK_PARAM(url, NULL);

    int err;

    gif_decoder_handler_t *hdl = (gif_decoder_handler_t *)aos_zalloc_check(sizeof(gif_decoder_handler_t));
    GifFileType * gif_file;

    hdl->stream = lstream_open(url);
    CHECK_RET_WITH_RET(hdl->stream, NULL);

    /* put handler to user data */
    if ((gif_file = DGifOpen(hdl, stream_read, &err)) == NULL) {
        PrintGifError(err);
        goto ERR;
    }

    if (gif_file->SHeight == 0 || gif_file->SWidth == 0) {
        LOGE(TAG, "Image of width or height 0");
        goto ERR;
    }
    hdl->gif_file = gif_file;

    /* 
     * Allocate the screen as vector of column of rows. Note this
     * screen is device independent - it's the screen defined by the
     * GIF file parameters.
     */
    GifRowType *  ScreenBuffer = (GifRowType *)aos_malloc_check(gif_file->SHeight * sizeof(GifRowType));
    int i;
    int width_size = gif_file->SWidth * sizeof(GifPixelType); /* Size in bytes one row.*/

    ScreenBuffer[0] = (GifRowType)aos_malloc_check(width_size);

    for (i = 0; i < gif_file->SWidth; i++) /* Set its color to BackGround. */
        ScreenBuffer[0][i] = gif_file->SBackGroundColor;

    for (i = 1; i < gif_file->SHeight; i++) {
        /* Allocate the other rows, and set their color to background too: */
        ScreenBuffer[i] = (GifRowType)aos_malloc_check(width_size);
        memcpy(ScreenBuffer[i], ScreenBuffer[0], width_size);
    }

    hdl->screen_buf = ScreenBuffer;

    return hdl;

ERR:
    gif_free(hdl);
    return NULL;
}

int gif_get_height(gif_decoder_handler_t *hdl)
{
    return hdl->gif_file->SHeight;
}

int gif_get_width(gif_decoder_handler_t *hdl)
{
    return hdl->gif_file->SWidth;
}

int gif_get_next_image(gif_decoder_handler_t *hdl, uint8_t *image_r, uint8_t *image_g, uint8_t *image_b, int *delay_ms)
{
    CHECK_PARAM(hdl && delay_ms, -1);

    int            ExtCode;
    GifRecordType RecordType = UNDEFINED_RECORD_TYPE;
    GifFileType * gif_file = hdl->gif_file;
    int         ret;
    GifByteType *Extension;

    /* check if already read all the records*/
    // if (hdl->file_terminated) {
    //     return -1;
    // }

    *delay_ms = 0;

    /* last fetch left one image, we don't need to do DGifGetImageDesc again */
    // if (hdl->current_image < gif_file->ImageCount) {
    //     ret = read_image(hdl, image_r, image_g, image_b);
    //     if (ret != 0) {
    //         LOGE(TAG, "read image error");
    //         return -1;
    //     }
    // }

    /* Scan the content of the GIF file and load the image(s) in: */
    do {
        if (DGifGetRecordType(gif_file, &RecordType) == GIF_ERROR) {
            PrintGifError(gif_file->Error);
            return -1;
        }

        switch (RecordType) {
        case IMAGE_DESC_RECORD_TYPE:
            if (DGifGetImageDesc(gif_file) == GIF_ERROR) {
                PrintGifError(gif_file->Error);
                return -1;
            }

            /* break out if we have got more than one image */
            // if (hdl->current_image + 1 < gif_file->ImageCount) {
            //     LOGD(TAG, "step into next image");
            //     break;
            // }

            ret = read_image(hdl, image_r, image_g, image_b);
            if (ret != 0) {
                LOGE(TAG, "read image error");
                return -1;
            } else {
                return 0;
            }

            break;

        case EXTENSION_RECORD_TYPE:
            /* Skip any extension blocks in file: */
            if (DGifGetExtension(gif_file, &ExtCode, &Extension) == GIF_ERROR) {
                PrintGifError(gif_file->Error);
                return -1;
            }

            if (ExtCode == GRAPHICS_EXT_FUNC_CODE) {
                GraphicsControlBlock gcb;
                if (Extension == NULL) {
                    LOGE(TAG, "Invalid extension block");
                    gif_file->Error = D_GIF_ERR_IMAGE_DEFECT;
                    PrintGifError(gif_file->Error);
                    return -1;
                }

                if (DGifExtensionToGCB(Extension[0], Extension+1, &gcb) == GIF_ERROR) {
                    PrintGifError(gif_file->Error);
                    return -1;
                }

                *delay_ms = gcb.DelayTime * 10;
                // LOGD(TAG, "image %d ext:", gif_file->ImageCount);
                // LOGD(TAG, "Disposal Mode: %d", gcb.DisposalMode);
                // LOGD(TAG, "User Input Flag: %d", gcb.UserInputFlag);
                // LOGD(TAG, "Transparency on: %s", gcb.TransparentColor != -1 ? "yes" : "no");
                LOGD(TAG, "image %d DelayTime: %d", gif_file->ImageCount, gcb.DelayTime);
                // LOGD(TAG, "Transparent Index: %d", gcb.TransparentColor);
                // printf("\n");
            }

            while (Extension != NULL) {
                if (DGifGetExtensionNext(gif_file, &Extension) == GIF_ERROR) {
                    PrintGifError(gif_file->Error);
                    return -1;
                }
            }
            break;
        case TERMINATE_RECORD_TYPE:
            break;
        default: /* Should be trapped by DGifGetRecordType. */
            break;
        }
    } while (RecordType != TERMINATE_RECORD_TYPE);

    /* already get all the images */
    if (RecordType == TERMINATE_RECORD_TYPE) {
        LOGD(TAG, "fetched all the images");
        return -1;
    }

    return 0;
}

int gif_free(gif_decoder_handler_t *hdl)
{
    CHECK_PARAM(hdl, -1);
    int Error;

    GifFileType *gif_file = hdl->gif_file;
    GifRowType *screen_buf = hdl->screen_buf;

    if (screen_buf) {
        for (int i = 0; i < gif_file->SHeight; i++) {
            aos_free(screen_buf[i]);
        }
        aos_free(screen_buf);
    }

    if (DGifCloseFile(gif_file, &Error) == GIF_ERROR) {
        PrintGifError(Error);
        return -1;
    }

    aos_free(hdl);
    return 0;
}

// unsigned char dot_gif[] = {
//   0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x11, 0x00, 0x05, 0x00, 0x87, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10,
//   0x10, 0x20, 0x20, 0x20, 0x2f, 0x2f, 0x2f, 0x3d, 0x3d, 0x3d, 0x4b, 0x4b,
//   0x4b, 0x58, 0x58, 0x58, 0x65, 0x65, 0x65, 0x71, 0x71, 0x71, 0x84, 0x84,
//   0x84, 0x96, 0x96, 0x96, 0xa5, 0xa5, 0xa5, 0xb2, 0xb2, 0xb2, 0xbe, 0xbe,
//   0xbe, 0xc8, 0xc8, 0xc8, 0xd3, 0xd3, 0xd3, 0xe0, 0xe0, 0xe0, 0xe9, 0xe9,
//   0xe9, 0xf0, 0xf0, 0xf0, 0xf4, 0xf4, 0xf4, 0xf7, 0xf7, 0xf7, 0xf9, 0xf9,
//   0xf9, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
//   0xfc, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd,
//   0xfd, 0x21, 0xff, 0x0b, 0x4e, 0x45, 0x54, 0x53, 0x43, 0x41, 0x50, 0x45,
//   0x32, 0x2e, 0x30, 0x03, 0x01, 0x00, 0x00, 0x00, 0x21, 0xf9, 0x04, 0x00,
//   0x64, 0x00, 0xff, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x05,
//   0x00, 0x00, 0x08, 0x14, 0x00, 0xe3, 0x08, 0x1c, 0x38, 0xd0, 0x1f, 0xc1,
//   0x83, 0x08, 0x13, 0x2a, 0x5c, 0xc8, 0xb0, 0xa1, 0xc3, 0x81, 0x01, 0x01,
//   0x00, 0x21, 0xf9, 0x04, 0x00, 0x64, 0x00, 0xff, 0x00, 0x2c, 0x00, 0x00,
//   0x00, 0x00, 0x11, 0x00, 0x05, 0x00, 0x00, 0x08, 0x14, 0x00, 0xe3, 0x08,
//   0x1c, 0x48, 0xb0, 0xa0, 0xc1, 0x82, 0xfe, 0x0e, 0x2a, 0x5c, 0xc8, 0xb0,
//   0xa1, 0xc3, 0x38, 0x01, 0x01, 0x00, 0x21, 0xf9, 0x04, 0x00, 0x64, 0x00,
//   0xff, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x05, 0x00, 0x00,
//   0x08, 0x12, 0x00, 0xe3, 0x08, 0x1c, 0x48, 0xb0, 0xa0, 0xc1, 0x83, 0x08,
//   0x0f, 0xfa, 0x4b, 0xc8, 0xb0, 0x61, 0xc3, 0x80, 0x00, 0x21, 0xf9, 0x04,
//   0x00, 0x64, 0x00, 0xff, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00,
//   0x05, 0x00, 0x00, 0x08, 0x14, 0x00, 0xe3, 0x08, 0x1c, 0x48, 0xb0, 0xa0,
//   0xc1, 0x83, 0x08, 0x13, 0x2a, 0x2c, 0xe8, 0x6f, 0xa1, 0xc3, 0x38, 0x01,
//   0x01, 0x00, 0x21, 0xf9, 0x04, 0x00, 0x64, 0x00, 0xff, 0x00, 0x2c, 0x00,
//   0x00, 0x00, 0x00, 0x11, 0x00, 0x05, 0x00, 0x00, 0x08, 0x12, 0x00, 0xe3,
//   0x08, 0x1c, 0x48, 0xb0, 0xa0, 0xc1, 0x83, 0x08, 0x13, 0x2a, 0x5c, 0xb8,
//   0xd0, 0xdf, 0xc1, 0x80, 0x00, 0x21, 0xf9, 0x04, 0x00, 0x64, 0x00, 0xff,
//   0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x05, 0x00, 0x00, 0x08,
//   0x12, 0x00, 0xe3, 0x08, 0x1c, 0x48, 0xb0, 0xa0, 0xc1, 0x83, 0x08, 0x13,
//   0x2a, 0x5c, 0xa8, 0xd0, 0x1f, 0xc2, 0x80, 0x00, 0x21, 0xf9, 0x04, 0x00,
//   0x64, 0x00, 0xff, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x05,
//   0x00, 0x00, 0x08, 0x12, 0x00, 0xe3, 0x08, 0x1c, 0x48, 0xb0, 0xa0, 0xc1,
//   0x83, 0x08, 0x13, 0x2a, 0x5c, 0x98, 0xd0, 0x5f, 0xc2, 0x80, 0x00, 0x21,
//   0xf9, 0x04, 0x00, 0x64, 0x00, 0xff, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00,
//   0x11, 0x00, 0x05, 0x00, 0x00, 0x08, 0x14, 0x00, 0xe3, 0x08, 0x1c, 0x48,
//   0xb0, 0xa0, 0xc1, 0x83, 0x08, 0x13, 0x2a, 0x1c, 0xe8, 0x6f, 0xa1, 0xc3,
//   0x81, 0x01, 0x01, 0x00, 0x21, 0xf9, 0x04, 0x00, 0x64, 0x00, 0xff, 0x00,
//   0x2c, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x05, 0x00, 0x00, 0x08, 0x14,
//   0x00, 0xe3, 0x08, 0x1c, 0x48, 0xb0, 0xa0, 0xc1, 0x83, 0x08, 0x0b, 0xfa,
//   0x4b, 0xc8, 0xb0, 0xa1, 0xc3, 0x38, 0x01, 0x01, 0x00, 0x21, 0xf9, 0x04,
//   0x00, 0x64, 0x00, 0xff, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00,
//   0x05, 0x00, 0x00, 0x08, 0x14, 0x00, 0xe3, 0x08, 0x1c, 0x48, 0xb0, 0xa0,
//   0xc1, 0x81, 0xfe, 0x0e, 0x2a, 0x5c, 0xc8, 0xb0, 0xa1, 0xc3, 0x81, 0x01,
//   0x01, 0x00, 0x21, 0xf9, 0x04, 0x00, 0x64, 0x00, 0xff, 0x00, 0x2c, 0x00,
//   0x00, 0x00, 0x00, 0x11, 0x00, 0x05, 0x00, 0x00, 0x08, 0x14, 0x00, 0xe3,
//   0x08, 0x1c, 0x18, 0xc7, 0x1f, 0xc1, 0x83, 0x08, 0x13, 0x2a, 0x5c, 0xc8,
//   0xb0, 0xa1, 0xc3, 0x83, 0x01, 0x01, 0x00, 0x21, 0xf9, 0x04, 0x00, 0x64,
//   0x00, 0xff, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x05, 0x00,
//   0x00, 0x08, 0x14, 0x00, 0xe3, 0x08, 0x1c, 0x28, 0xd0, 0x1f, 0xc1, 0x83,
//   0x08, 0x13, 0x2a, 0x5c, 0xc8, 0xb0, 0xa1, 0x43, 0x82, 0x01, 0x01, 0x00,
//   0x3b
// };
// unsigned int dot_gif_len = 1285;

// int gif_decoder_test()
// {
//     gif_decoder_handler_t *hdl = gif_new(dot_gif, dot_gif_len);
//     int height = gif_get_height(hdl);
//     int width = gif_get_width(hdl);
//     int ret;

//     if (height <= 0 || width <= 0) {
//         printf("size error %d %d\n", height, width);
//         exit(-1);
//     }

//     uint8_t *image_r = aos_zalloc(height * width);
//     uint8_t *image_b = aos_zalloc(height * width);
//     int delay_ms;

//     for (int cnt = 0; cnt < 100; cnt++) {

//         ret = gif_get_next_image(hdl, image_r, NULL, image_b, &delay_ms);

//         if (ret < 0) {
//             break;
//         }

//         printf("git get image r delay=%d ms:\n", delay_ms);
//         for (int i = 0; i < height; i++) {
//             for (int j = 0; j < width; j++) {
//                 printf("0x%02x ", image_r[i * width + j]);
//             }
//             printf("\n");
//         }
//         printf("\n");

//         printf("git get image b delay=%d ms:\n", delay_ms);
//         for (int i = 0; i < height; i++) {
//             for (int j = 0; j < width; j++) {
//                 printf("0x%02x ", image_b[i * width + j]);
//             }
//             printf("\n");
//         }
//         printf("\n");
        
//     }

//     gif_free(hdl);
// }
